#ifdef _WIN32
#include <windows.h>
#endif

#include <string>
#include <cstdlib>
#include "glee/GLee.h"
#include <GL/glu.h>
#include "robot.h"
#include "glslshader.h"
#include "md2model.h"
#include "collider.h"
#include "gameworld.h"
#include "player.h"
#include "landscape.h"
#include "AABBCollider.h"
using std::string;

const string ROBOT_MODEL = "data/models/Robot/robot.md2";
const string ROBOT_TEXTURE = "data/models/Robot/robotTex.tga";

Robot::Robot(GameWorld* world):
Enemy(world),
m_AIState(ROBOT_IDLE),
m_currentTime(0),
m_lastAIChange(0)
{
	string vertexShader = "data/shaders/glsl1.20/model.vert";
    string fragmentShader = "data/shaders/glsl1.20/model.frag";
    m_model = new MD2Model(vertexShader, fragmentShader);
    m_model->setAnimation(Animation::IDLE);
	setVelocity(0.0f,0.0f,0.0f);
	setGravity(true);
	m_collider = new AABBCollider(this,0.75f,1.1f,0.75f);
	m_key = -1;
}


Robot::~Robot(void)
{
	delete m_model;
}

void Robot::onPrepare(float dT)
{
    getCollider()->setRadius(m_model->getRadius());

    m_currentTime += dT;

    processAI();

    m_model->update(dT);

    if (m_position.y > 0.0f) {
        m_position.y -= 10.0f * dT;
    }

    Vector3 pos = getPosition();

    float speed = 0.0f;

    if (m_AIState == ROBOT_RUNNING)
    {
        speed = 2.0f * dT;
    }

    float cosYaw = cosf(degreesToRadians(m_yaw));
    float sinYaw = sinf(degreesToRadians(m_yaw));
    pos.x += float(cosYaw) * speed;
    pos.z += float(sinYaw) * speed;

    setPosition(pos);


}

void Robot::onRender() const
{

    glPushMatrix();
        Vector3 pos = getPosition();
        glTranslatef(pos.x, pos.y, pos.z);
        glRotatef(getYaw(), 0.0f, -1.0f, 0.0f);
        glBindTexture(GL_TEXTURE_2D, m_robotTextureID);
        m_model->render();
    glPopMatrix();
}

void Robot::onPostRender()
{

}

bool Robot::onInitialize()
{
    bool result = m_model->load(ROBOT_MODEL, 12);
    if (result)
    {
        if (!m_robotTexture.load(ROBOT_TEXTURE))
        {
            result = false;
        }
        else
        {
            glGenTextures(1, &m_robotTextureID);
            glActiveTexture(GL_TEXTURE0);
            glBindTexture(GL_TEXTURE_2D, m_robotTextureID);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

            gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB8, m_robotTexture.getWidth(),
                              m_robotTexture.getHeight(), GL_RGB, GL_UNSIGNED_BYTE,
                              m_robotTexture.getImageData());
        }
    }

    m_yaw = (float(rand()) / RAND_MAX) * 360.0f;
    return result;
}

void Robot::onShutdown()
{

}

RobotAIState getRandomIdleState()
{
	return ROBOT_IDLE;
    int result = rand() % 3;
    if (result == 0)
    {
        return ROBOT_IDLE;
    }
}


void Robot::processAI()
{
    if (isDead())
    {
        return;
    }

    const float DANGER_DISTANCE = 5.0f;

    Vector3 playerPosition = getWorld()->getPlayer()->getPosition();
    Vector3 playerDirection = getPosition() - playerPosition;
    float playerDistance = playerDirection.length();

    if (playerDistance < DANGER_DISTANCE && m_AIState != ROBOT_RUNNING && (m_currentTime - m_lastAIChange) > 3.0f)
    {
        m_model->setAnimation(Animation::IDLE);
        m_AIState = ROBOT_RUNNING;
        m_lastAIChange = m_currentTime;
    }

    if (playerDistance >= DANGER_DISTANCE)
    {
        if (((m_currentTime + float(rand() % 5) / 10.0f) - m_lastAIChange) > 8.0f)
        {
            RobotAIState newState = getRandomIdleState();
            if (newState != m_AIState)
            {
                m_AIState = newState;
                m_lastAIChange = m_currentTime;
                if (newState == ROBOT_IDLE)
                {
                    m_model->setAnimation(Animation::RUN);
                }
            }
        }
    }

    //Stop the Ogro's going outside the map bounds
    float minX = getWorld()->getLandscape()->getTerrain()->getMinX() + 2.5f;
    float maxX = getWorld()->getLandscape()->getTerrain()->getMaxX() - 2.5f;
    float minZ = getWorld()->getLandscape()->getTerrain()->getMinZ() + 2.5f;
    float maxZ = getWorld()->getLandscape()->getTerrain()->getMaxZ() - 2.5f;

    float randYaw = 90.0f + (float) (rand() % 90);

    if (getPosition().x < minX ||
        getPosition().x > maxX ||
        getPosition().z < minZ ||
        getPosition().z > maxZ)
    {
        m_yaw += randYaw;
        m_AIState = ROBOT_RUNNING;//ROBOT_WALK;
        m_model->setAnimation(Animation::IDLE);
        m_lastAIChange = m_currentTime;

        if (getPosition().x < minX)
        {
            m_position.x = minX;
        }
        else if (getPosition().x > maxX)
        {
            m_position.x = maxX;
        }
        else if (getPosition().z < minZ)
        {
            m_position.z = minZ;
        }
        else if (getPosition().z > maxZ)
        {
            m_position.z = maxZ;
        }
    }


}


void Robot::onKill()
{/*
    int r = (int) rand() % 3;
    if (r == 0)
    {
        m_model->setAnimation(Animation::DEATH1);
    }
    else if (r == 1)
    {
        m_model->setAnimation(Animation::DEATH2);
    }
    else
    {
        m_model->setAnimation(Animation::DEATH3);
    }

    m_AIState = ROBOT_DEAD;*/
}

void Robot::onResurrection()
{
 //   m_model->setAnimation(Animation::IDLE);
 //   m_AIState = ROBOT_IDLE;
  //  m_lastAIChange = m_currentTime;
}
